package com.edu.service.impl;

import com.api.course.CourseClient;
import com.edu.entity.ESCourse;
import com.edu.entity.HfdClassInfo;

import com.edu.entity.SearchPageResult;
import com.edu.service.ISearchService;
import com.edu.vo.PageResultVO;
import com.edu.vo.Result;

import org.checkerframework.checker.units.qual.A;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.MatchQueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.index.query.TermQueryBuilder;
import org.elasticsearch.search.aggregations.AggregationBuilders;
import org.elasticsearch.search.aggregations.Aggregations;
import org.elasticsearch.search.aggregations.bucket.terms.Terms;
import org.elasticsearch.search.aggregations.bucket.terms.TermsAggregationBuilder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.elasticsearch.core.ElasticsearchRestTemplate;
import org.springframework.data.elasticsearch.core.SearchHit;
import org.springframework.data.elasticsearch.core.SearchHits;
import org.springframework.data.elasticsearch.core.query.NativeSearchQuery;
import org.springframework.data.elasticsearch.core.query.NativeSearchQueryBuilder;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;

@Service
public class SearchService implements ISearchService {

    @Autowired(required = false)
    private CourseClient courseClient;

    @Autowired
    private ElasticsearchRestTemplate template;

    @Override
    public Result initData2es() {

        //1.获取审核通过的class spu信息
        List<HfdClassInfo> classInfo = courseClient.findClassInfo();



        //2.同步es库
        classInfo.forEach(spu->{
            //spu->同步到es库（ESCourse）
            ESCourse esCourse = new ESCourse();

            esCourse.setClassId(spu.getClassId());
            esCourse.setClassName(spu.getName());
            esCourse.setSignTime(spu.getSignTime());
            esCourse.setStartTime(spu.getStartTime());
            esCourse.setEndTime(spu.getEndTime());
            esCourse.setMoney(spu.getMoney().doubleValue());
            esCourse.setGradeId(spu.getGradeInfo().getGradeId());
            esCourse.setGradeName(spu.getGradeInfo().getName());
            esCourse.setSubjectId(spu.getSubjectInfo().getSubjectId());
            esCourse.setSubjectName(spu.getSubjectInfo().getName());

            //这里教师信息用集合的方式存储
            esCourse.setTeacherInfoList(spu.getTeacherInfoList());

//            for (HfdTeacherInfo teacherList : spu.getTeacherInfoList()) {
//                Integer teacherId = teacherList.getTeacherId();
//                esCourse.setTeacherId(teacherId);
//
//                String teacherName = teacherList.getName();
//                esCourse.setTeacherName(teacherName);
//
//                String icon = teacherList.getIcon();
//                esCourse.setIcon(icon);
//            }

            template.save(esCourse);
        });
        return new Result(true ,0 , "初始化成功");
    }

//    @Override
//    public Result course2es(HfdClassInfo spu) {
//
//        //spu->同步到es库（ESCourse）
//        ESCourse esCourse = new ESCourse();
//
//        esCourse.setClassId(spu.getClassId());
//        esCourse.setClassName(spu.getName());
//        esCourse.setSignTime(spu.getSignTime());
//        esCourse.setStartTime(spu.getStartTime());
//        esCourse.setEndTime(spu.getEndTime());
//        esCourse.setMoney(spu.getMoney().doubleValue());
//        esCourse.setGradeId(spu.getGradeInfo().getGradeId());
//        esCourse.setGradeName(spu.getGradeInfo().getName());
//        esCourse.setSubjectId(spu.getSubjectInfo().getSubjectId());
//        esCourse.setSubjectName(spu.getSubjectInfo().getName());
//
//        //这里教师信息用集合的方式存储
//        esCourse.setTeacherInfoList(spu.getTeacherInfoList());
//
//        template.save(esCourse);
//
//        return new Result(true ,0 , "同步成功");
//    }

    @Override
    public PageResultVO<ESCourse> search(Map searchMap) {

        if(searchMap == null){
            return new PageResultVO<>(1 , "参数非法");
        }

        //1.指定查询方式（复合查询） 这个功能可能用不上
        BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
        if(!StringUtils.isEmpty(searchMap.get("keyword"))){//keyword是前端输入框携带的搜索信息，功能先做，但是前端不一定用
            //三个域复合查询，用should。只要有一个符合就会搜索出来。
            MatchQueryBuilder classNameMatchQueryBuilder = QueryBuilders.matchQuery("className" , searchMap.get("keyword"));
            MatchQueryBuilder gradeNameMatchQueryBuilder = QueryBuilders.matchQuery("gradeName" , searchMap.get("keyword"));
            MatchQueryBuilder subjectNameMatchQueryBuilder = QueryBuilders.matchQuery("subjectName" , searchMap.get("keyword"));

            boolQueryBuilder.should(classNameMatchQueryBuilder);
            boolQueryBuilder.should(gradeNameMatchQueryBuilder);
            boolQueryBuilder.should(subjectNameMatchQueryBuilder);

        }

        //2.设置分页
        //设置分页信息
        int page = 0;//如果前端没有传分页,就以第一页为准
        if(!StringUtils.isEmpty(searchMap.get("page"))) {
            page = (int)searchMap.get("page");
            page --;
        }

        int size = 4;//如果前端没有传分页，就以两条信息为准
        if(!StringUtils.isEmpty(searchMap.get("size"))){
            size = (int)searchMap.get("size");
        }

        PageRequest pageRequest = PageRequest.of(page , size);

        //3.聚合年级和学科
        TermsAggregationBuilder gradeNameAgg = AggregationBuilders.terms("gradeName_agg")
                .field("gradeName.keyword"); //聚合年级

        TermsAggregationBuilder subjectNameAgg = AggregationBuilders.terms("subjectName_agg")
                .field("subjectName.keyword"); //聚合学科

        //4.过滤 年级、学科
        if(!StringUtils.isEmpty(searchMap.get("gradeNameFilter"))){
            TermQueryBuilder gradeNameFilterBuilder = QueryBuilders
                    .termQuery("gradeName.keyword" , searchMap.get("gradeNameFilter"));
            boolQueryBuilder.filter(gradeNameFilterBuilder);
        }

        if(!StringUtils.isEmpty(searchMap.get("subjectNameFilter"))){
            TermQueryBuilder subjectNameFilterBuilder = QueryBuilders
                    .termQuery("subjectName.keyword" , searchMap.get("subjectNameFilter"));
            boolQueryBuilder.filter(subjectNameFilterBuilder);
        }

        NativeSearchQuery builder = new NativeSearchQueryBuilder()
                //设置查询方式
                .withQuery(boolQueryBuilder)
                //设置分页
                .withPageable(pageRequest)
                //聚合年级
                .addAggregation(gradeNameAgg)
                //聚合学科
                .addAggregation(subjectNameAgg)
                .build();


        SearchHits<ESCourse> res = template.search(builder, ESCourse.class);

        //获取分页信息
        long totalHits = res.getTotalHits(); //总记录数
        //获取当前页数据
        List<ESCourse>  esCourseList = new ArrayList<>();//当前页数据放入集合

        List<SearchHit<ESCourse>> searchHits = res.getSearchHits();
        searchHits.forEach(hit->{
            ESCourse content = hit.getContent();
            esCourseList.add(content);
        });

        //获取聚合信息
        Aggregations aggregations = res.getAggregations();
        //用一个集合装取subjectName_agg下面的三级分类信息
        List subjectNameList = new ArrayList();
        //取cat3Name_agg
        Terms subjectName_agg = aggregations.get("subjectName_agg");
        List<? extends Terms.Bucket> subjectName_aggBuckets = subjectName_agg.getBuckets();
        subjectName_aggBuckets.forEach(b->{
            Object key = b.getKey();
            subjectNameList.add(key);
        });

        //获取品牌聚合信息
        //用一个集合装取gradeName_agg下面的三级分类信息
        List gradeNameList = new ArrayList();
        //取gradeName_agg
        Terms gradeName_agg = aggregations.get("gradeName_agg");
        List<? extends Terms.Bucket> gradeName_aggBuckets = gradeName_agg.getBuckets();
        gradeName_aggBuckets.forEach(b->{
            Object key = b.getKey();
            gradeNameList.add(key);
        });

        //PageResultVO
        SearchPageResult pageInfo = new SearchPageResult();
        pageInfo.setData(esCourseList);
        pageInfo.setCount(totalHits);
        pageInfo.setGradeNameList(gradeNameList);
        pageInfo.setSubjectNameList(subjectNameList);
        return pageInfo;
    }


}

